﻿using Newtonsoft.Json;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;

namespace ImageGenerator.Helpers;

public class LicenseHelper
{
    private string hardwareId = "";
    public string HardwareId
    {
        get
        {
            if (string.IsNullOrWhiteSpace(hardwareId))
                return GetHardwareId();
            return hardwareId;
        }
        set { hardwareId = value; }
    }

    private Tuple<bool?, DateTime?> validation = new(null, null);
    public Tuple<bool?, DateTime?> Validation
    {
        get
        {
            if (validation.Item1 == null)
                return ValidateLicense();
            return validation;
        }
    }

    // 获取硬件ID
    public string GetHardwareId()
    {
        var cpuId = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor")
            .Get()
            .Cast<ManagementObject>()
            .Select(mo => mo["ProcessorId"]?.ToString() ?? "UnknownProcessorId")
            .FirstOrDefault() ?? "";


        //// 获取硬盘序列号
        //mos = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
        //foreach (ManagementObject mo in mos.Get())
        //{
        //    id += mo["SerialNumber"].ToString();
        //    break;
        //}

        // 获取网卡MAC地址
        //mos = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = true");
        //foreach (ManagementObject mo in mos.Get())
        //{
        //    id += mo["MACAddress"].ToString();
        //    break;
        //}
        HardwareId = cpuId;
        return cpuId;
    }

    private readonly byte[] key = Encoding.UTF8.GetBytes("1q2w3e4r5t6y7u8i9o0p1Q2W3E4R5T6Y7U8I9O0P"[..32]);
    private readonly byte[] iv = Encoding.UTF8.GetBytes("1A2S3D4F5G6H7J8K9L1a2s3d4f5g6h7j8k9l"[..16]);

    public string Encrypt(DateTime expirationDate)
    {
        using Aes aesAlg = Aes.Create();
        aesAlg.Key = key; // 截取前32位作为密钥
        aesAlg.IV = iv; // 初始化向量，通常也是随机生成的，这里为了简化直接用空字节填充

        var dataToEncrypt = new { Text = HardwareId, Expiration = expirationDate.AddDays(1).Date };
        string json = JsonConvert.SerializeObject(dataToEncrypt);

        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        using MemoryStream ms = new();
        using (CryptoStream cs = new(ms, encryptor, CryptoStreamMode.Write))
        {
            using StreamWriter sw = new(cs);
            sw.Write(json);
        }
        return Convert.ToBase64String(ms.ToArray());
    }

    public (string DecryptedText, DateTime ExpirationDate) Decrypt(string cipherText)
    {
        using Aes aesAlg = Aes.Create();
        aesAlg.Key = key;
        aesAlg.IV = iv;

        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
        byte[] encryptedData = Convert.FromBase64String(cipherText);

        using MemoryStream ms = new(encryptedData);
        using CryptoStream cs = new(ms, decryptor, CryptoStreamMode.Read);
        using StreamReader sr = new(cs);
        string json = sr.ReadToEnd();
        dynamic decryptedData = JsonConvert.DeserializeObject(json);
        DateTime expirationDate = decryptedData.Expiration;
        string text = decryptedData.Text;
        return (text, expirationDate);
    }

    // 验证授权密钥
    public Tuple<bool?, DateTime?> ValidateLicense()
    {
        var licensePath = Path.Combine(Directory.GetCurrentDirectory(), "license.key");
        if (File.Exists(licensePath))
        {
            string licenseKey = File.ReadAllText(licensePath);

            var (decryptedText, expirationDate) = Decrypt(licenseKey);

            if (decryptedText != HardwareId)
                return new(false, null);
            if (DateTime.Now >= expirationDate)
                return new(false, expirationDate);
            return new(true, expirationDate);
        }
        else
            return new(null, null);
    }
}
